/************************************************ 
* WKS GD32F470ZIT6���İ�
* SD����ʼ�� ����	   
* �汾��V1.0								  
************************************************/	

#include "sd_conf.h"


sd_card_info_struct sd_cardinfo;                            /* SD����Ϣ */

/**
 * @brief       ��ʼ��SD������ȡSD����Ϣ����������ģʽ�ʹ���ģʽ
 * @param       ��
 * @retval      sd_error_enum
 */
sd_error_enum sdio_sd_init(void)
{
    sd_error_enum status = SD_OK;
    uint32_t cardstate = 0;
  
    status = sd_init();     /* ��ʼ��SD�� */
  
    nvic_irq_enable(SDIO_IRQn, 0, 0);    /* SDIO�ж����ã���ռ���ȼ�0�������ȼ�0 */
   
    if(SD_OK == status)
    {
        status = sd_card_information_get(&sd_cardinfo);  /* ��ȡ����Ϣ */
    }
    
    if(SD_OK == status)       
    {
        status = sd_card_select_deselect(sd_cardinfo.card_rca);  /* ѡ��SD�� */
    } 
    
    status = sd_cardstatus_get(&cardstate);   /* ��ȡ��״̬ */
    if(cardstate & 0x02000000)                /* ����ס�� */                    
    {
        yz_info("\r\n the card is locked!");
    }
    
    if((SD_OK == status) && (!(cardstate & 0x02000000))) 
    {
        /* ��������ģʽ */
        status = sd_bus_mode_config(SDIO_BUSMODE_4BIT);     /* 4λSDIO������ģʽ */ 
//      status = sd_bus_mode_config(SDIO_BUSMODE_1BIT);
    }
    
    if(SD_OK == status)
    {
        /* ���ô��䷽ʽ */
      status = sd_transfer_mode_config(SD_DMA_MODE);
//        status = sd_transfer_mode_config(SD_POLLING_MODE);  /* ����Ϊ��ѯģʽ */
    }
    
    return status;
}

/**
 * @brief       ͨ�����ڴ�ӡSD�������Ϣ
 * @param       ��
 * @retval      ��
 */
void card_info_get(void)
{
    uint8_t sd_spec, sd_spec3, sd_spec4, sd_security;
    uint32_t block_count, block_size;
    uint16_t temp_ccc;
  
    yz_info("Card information:\n");
    sd_spec = (sd_scr[1] & 0x0F000000) >> 24;
    sd_spec3 = (sd_scr[1] & 0x00008000) >> 15;
    sd_spec4 = (sd_scr[1] & 0x00000400) >> 10; /* SD��SCR�Ĵ�������ȡSD���汾��Ϣ */

    if(2 == sd_spec)
    {
        if(1 == sd_spec3)
        {
            if(1 == sd_spec4)
            {
                yz_info("## Card version 4.xx ##\n");
            }
            else
            {
                yz_info("## Card version 3.0x ##\n");
            }
        }
        else
        {
            yz_info("## Card version 2.00 ##\n");
        }
    }
    else if(1 == sd_spec)
    {
        yz_info("## Card version 1.10 ##\n");
    }
    else if(0 == sd_spec)
    {
        yz_info("## Card version 1.0x ##\n");
    }

    sd_security = (sd_scr[1] & 0x00700000) >> 20;
    if(2 == sd_security) {
        yz_info("## SDSC card ##\n");
    } else if(3 == sd_security) {
        yz_info("## SDHC card ##\n");
    } else if(4 == sd_security) {
        yz_info("## SDXC card ##\n");
    }

    block_count = (sd_cardinfo.card_csd.c_size + 1) * 1024;
    block_size = 512;
    yz_info("## Device size is %luKB ##\n", sd_card_capacity_get());  /* ��ʾ���� */
    yz_info("## Block size is %lu B ##\n", block_size);                /* ��ʾ���С */
    yz_info("## Block count is %lu ##\n", block_count);               /* ��ʾ������ */

    if(sd_cardinfo.card_csd.read_bl_partial)
    {
        yz_info("## Partial blocks for read allowed ##\n");
    }
    if(sd_cardinfo.card_csd.write_bl_partial)
    {
        yz_info("## Partial blocks for write allowed ##\n");
    }

    temp_ccc = sd_cardinfo.card_csd.ccc;                              /* SD��������� */
    yz_info("## CardCommandClasses is: %x ##\n", temp_ccc);
    if((SD_CCC_BLOCK_READ & temp_ccc) && (SD_CCC_BLOCK_WRITE & temp_ccc))
    {
        yz_info("## Block operation supported ##\n");
    }
    if(SD_CCC_ERASE & temp_ccc)
    {
        yz_info("## Erase supported ##\n");
    }
    if(SD_CCC_WRITE_PROTECTION & temp_ccc)
    {
        yz_info("## Write protection supported ##\n");
    }
    if(SD_CCC_LOCK_CARD & temp_ccc)
    {
        yz_info("## Lock unlock supported ##\n");
    }
    if(SD_CCC_APPLICATION_SPECIFIC & temp_ccc)
    {
        yz_info("## Application specific supported ##\n");
    }
    if(SD_CCC_IO_MODE & temp_ccc)
    {
        yz_info("## I/O mode supported ##\n");
    }
    if(SD_CCC_SWITCH & temp_ccc)
    {
        yz_info("## Switch function supported ##\n");
    }
}

/**
 * @brief       ��SD��(fatfs/usb����)
 * @param       pbuf  : ���ݻ�����
 * @param       saddr : ������ַ
 * @param       cnt   : ��������
 * @retval      SD_OK, ����;  ����, �������(���sd_error_enum����);
 */
sd_error_enum sd_read_disk(uint8_t *pbuf, uint32_t saddr, uint32_t cnt)
{
    sd_error_enum status = SD_OK;
    long long lsaddr = saddr;

    lsaddr <<= 9;

    if (cnt == 1)
    {
        status = sd_block_read((uint32_t*)pbuf, lsaddr, 512);               /* ��ȡ����block */
    }
		else 
    {
        status = sd_multiblocks_read((uint32_t*)pbuf, lsaddr, 512, cnt);    /* ��ȡ���block */  
    }

    return status;
}

/**
 * @brief       дSD��(fatfs/usb����)
 * @param       pbuf  : ���ݻ�����
 * @param       saddr : ������ַ
 * @param       cnt   : ��������
 * @retval      SD_OK, ����;  ����, �������(���sd_error_enum����);
 */
sd_error_enum sd_write_disk(uint8_t *pbuf, uint32_t saddr, uint32_t cnt)
{
    sd_error_enum status = SD_OK;
    long long lsaddr = saddr;

    lsaddr <<= 9;

    if (cnt == 1)
    {
        status = sd_block_write((uint32_t*)pbuf, lsaddr, 512);    	        /* д����block */
    }
		else 
    {
        status = sd_multiblocks_write((uint32_t*)pbuf, lsaddr, 512, cnt);   /* д���block */  
    }

    return status;  
}



